using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using UnityEngine;
using System.Threading;
using UnityEngine.Video;

namespace EntityKit.Runtime
{
    public static class LocalizationKit
    {
        private static Language _currentLanguage = Language.Unspecified;
        
        // 添加缓存机制
        private static readonly Dictionary<string, string> mTextCache = new Dictionary<string, string>();
        private static readonly Dictionary<string, Sprite> mImageSpriteCache = new Dictionary<string, Sprite>();
        private static readonly Dictionary<string, Texture> mImageTextureCache = new Dictionary<string, Texture>();
        private static readonly Dictionary<string, AudioClip> mAudioCache = new Dictionary<string, AudioClip>();
        private static readonly Dictionary<string, Font> mFontCache = new Dictionary<string, Font>();
        private static readonly Dictionary<string, VideoClip> mVideoCache = new Dictionary<string, VideoClip>();
        private static readonly Dictionary<string, GameObject> mPrefabCache = new Dictionary<string, GameObject>();
        private static readonly Dictionary<string, ScriptableObject> mScriptableObjectCache = new Dictionary<string, ScriptableObject>();
        private static readonly Dictionary<string, TextAsset> mTextAssetCache = new Dictionary<string, TextAsset>();

        public static Language CurrentLanguage
        {
            get
            {
                if (_currentLanguage == Language.Unspecified)
                {
                    _currentLanguage = Language.ChineseSimplified;
                }

                return _currentLanguage;
            }
            set
            {
                if (_currentLanguage != value)
                {
                    _currentLanguage = value;
                    // 语言改变时清空缓存
                    ClearCache();
                    EventKit.SendMessage(EventLocalizationLanguageChanged.Create(CurrentLanguage));
                }
            }
        }


        private static LocalizationConfig mConfigurations;

        public static void Initialize(LocalizationConfig config, Language defaultLanguage = Language.Unspecified)
        {
            mConfigurations = config;
            _currentLanguage = defaultLanguage;
            ClearCache(); // 初始化时清空缓存
        }

        public static void Release()
        {
            mImageAssetRootPath = string.Empty;
            mAudioAssetRootPath = string.Empty;
            mVideoAssetRootPath = string.Empty;
            mFontAssetRootPath = string.Empty;
            mPrefabAssetRootPath = string.Empty;
            mScriptableObjectAssetRootPath = string.Empty;
            mTextAssetAssetRootPath = string.Empty;
            mConfigurations = null;
            ClearCache(); // 释放时清空缓存
        }
        
        // 清空缓存
        private static void ClearCache()
        {
            mTextCache.Clear();
            mImageSpriteCache.Clear();
            mImageTextureCache.Clear();
            mAudioCache.Clear();
            mFontCache.Clear();
            mVideoCache.Clear();
            mPrefabCache.Clear();
            mScriptableObjectCache.Clear();
            mTextAssetCache.Clear();
        }

        #region Text

        public static bool ContainsTextKey(string key)
        {
            if (mConfigurations == null)
            {
                return false;
            }

            string value;
            return mConfigurations.TryGetValue(CurrentLanguage, LocalizationType.Text, key, out value);
        }

        public static string GetTextValue(string key)
        {
            // 使用缓存
            if (mTextCache.ContainsKey(key))
            {
                return mTextCache[key];
            }
            
            string value = string.Empty;
            if (mConfigurations != null)
            {
                mConfigurations.TryGetValue(CurrentLanguage, LocalizationType.Text, key, out value);
            }
            value = value.FormatText();
            mTextCache[key] = value; // 添加到缓存
            return value;
        }


        public static string GetTextValue(string key, Dictionary<string, object> parameters)
        {
            var template = GetTextValue(key);
            return StringHelper.Format(template, parameters);
        }


        public static string GetTextValue(string key, params object[] args)
        {
            var template = GetTextValue(key);
            return StringHelper.Format(template, args);
        }

        #endregion

        #region Image

        private static string mImageAssetRootPath = string.Empty;

        public static void SetImageRootPath(string rootPath)
        {
            mImageAssetRootPath = rootPath;
        }

        public static bool ContainsImageKey(string key)
        {
            if (mConfigurations == null)
            {
                return false;
            }

            string value;
            return mConfigurations.TryGetValue(CurrentLanguage, LocalizationType.Image, key, out value);
        }
        
        
        public static string GetImageValue(string key)
        {
            string value = string.Empty;
            if (mConfigurations != null)
            {
                mConfigurations.TryGetValue(CurrentLanguage, LocalizationType.Image, key, out value);
            }
            return value.FormatText();
        }

        public static async Task<Sprite> GetImageAsset2SpriteAsync(string key, CancellationToken cancellationToken = default)
        {
            // 使用缓存
            if (mImageSpriteCache.ContainsKey(key) && mImageSpriteCache[key] != null)
            {
                return mImageSpriteCache[key];
            }
            
            var imageValue = GetImageValue(key);
            if (string.IsNullOrEmpty(imageValue))
            {
                Debug.LogWarning($"找不到键为 {key} 的图片资源");
                return null;
            }
            
            var assetPath = FileHelper.NormalizePathToForwardSlash(Path.Combine(mImageAssetRootPath, _currentLanguage.ToString(), imageValue));
            var sprite = await AssetHelper.LoadAssetAsync<Sprite>(assetPath, cancellationToken);
            mImageSpriteCache[key] = sprite; // 添加到缓存
            return sprite;
        }
        
        public static Sprite GetImageAsset2SpriteSync(string key)
        {
            // 使用缓存
            if (mImageSpriteCache.ContainsKey(key) && mImageSpriteCache[key] != null)
            {
                return mImageSpriteCache[key];
            }
            
            var imageValue = GetImageValue(key);
            if (string.IsNullOrEmpty(imageValue))
            {
                Debug.LogWarning($"找不到键为 {key} 的图片资源");
                return null;
            }
            
            var assetPath = FileHelper.NormalizePathToForwardSlash(Path.Combine(mImageAssetRootPath, _currentLanguage.ToString(), imageValue));
            var sprite = AssetHelper.LoadAssetSync<Sprite>(assetPath);
            mImageSpriteCache[key] = sprite; // 添加到缓存
            return sprite;
        }
        
        public static async Task<Texture> GetImageAsset2TextureAsync(string key, CancellationToken cancellationToken = default)
        {
            // 使用缓存
            if (mImageTextureCache.ContainsKey(key) && mImageTextureCache[key] != null)
            {
                return mImageTextureCache[key];
            }
            
            var imageValue = GetImageValue(key);
            if (string.IsNullOrEmpty(imageValue))
            {
                Debug.LogWarning($"找不到键为 {key} 的图片资源");
                return null;
            }
            
            var assetPath = FileHelper.NormalizePathToForwardSlash(Path.Combine(mImageAssetRootPath, _currentLanguage.ToString(), imageValue));
            var texture = await AssetHelper.LoadAssetAsync<Texture>(assetPath, cancellationToken);
            mImageTextureCache[key] = texture; // 添加到缓存
            return texture;
        }
        
        public static Texture GetImageAsset2TextureSync(string key)
        {
            // 使用缓存
            if (mImageTextureCache.ContainsKey(key) && mImageTextureCache[key] != null)
            {
                return mImageTextureCache[key];
            }
            
            var imageValue = GetImageValue(key);
            if (string.IsNullOrEmpty(imageValue))
            {
                Debug.LogWarning($"找不到键为 {key} 的图片资源");
                return null;
            }
            
            var assetPath = FileHelper.NormalizePathToForwardSlash(Path.Combine(mImageAssetRootPath, _currentLanguage.ToString(), imageValue));
            var texture = AssetHelper.LoadAssetSync<Texture>(assetPath);
            mImageTextureCache[key] = texture; // 添加到缓存
            return texture;
        }

        # endregion

        #region Audio Clip

        private static string mAudioAssetRootPath = string.Empty;

        public static void SetAudioRootPath(string rootPath)
        {
            mAudioAssetRootPath = rootPath;
        }

        public static bool ContainsAudioKey(string key)
        {
            if (mConfigurations == null)
            {
                return false;
            }

            string value;
            return mConfigurations.TryGetValue(CurrentLanguage, LocalizationType.Audio, key, out value);
        }
        
        
        public static string GetAudioValue(string key)
        {
            string value = string.Empty;
            if (mConfigurations != null)
            {
                mConfigurations.TryGetValue(CurrentLanguage, LocalizationType.Audio, key, out value);
            }
            return value.FormatText();
        }
        
        
        public static async Task<AudioClip> GetAudioAssetAsync(string key, CancellationToken cancellationToken = default)
        {
            // 使用缓存
            if (mAudioCache.ContainsKey(key) && mAudioCache[key] != null)
            {
                return mAudioCache[key];
            }
            
            var audioValue = GetAudioValue(key);
            if (string.IsNullOrEmpty(audioValue))
            {
                Debug.LogWarning($"找不到键为 {key} 的音频资源");
                return null;
            }
            
            var assetPath = FileHelper.NormalizePathToForwardSlash(Path.Combine(mAudioAssetRootPath, _currentLanguage.ToString(), audioValue));
            var audioClip = await AssetHelper.LoadAssetAsync<AudioClip>(assetPath, cancellationToken);
            mAudioCache[key] = audioClip; // 添加到缓存
            return audioClip;
        }
        
        public static AudioClip GetAudioAssetSync(string key)
        {
            // 使用缓存
            if (mAudioCache.ContainsKey(key) && mAudioCache[key] != null)
            {
                return mAudioCache[key];
            }
            
            var audioValue = GetAudioValue(key);
            if (string.IsNullOrEmpty(audioValue))
            {
                Debug.LogWarning($"找不到键为 {key} 的音频资源");
                return null;
            }
            
            var assetPath = FileHelper.NormalizePathToForwardSlash(Path.Combine(mAudioAssetRootPath, _currentLanguage.ToString(), audioValue));
            var audioClip = AssetHelper.LoadAssetSync<AudioClip>(assetPath);
            mAudioCache[key] = audioClip; // 添加到缓存
            return audioClip;
        }
        
        
        #endregion

        #region Video

        
        private static string mVideoAssetRootPath = string.Empty;
        
        public static void SetVideoRootPath(string rootPath)
        {
            mVideoAssetRootPath = rootPath;
        }
        
        public static bool ContainsVideoKey(string key)
        {
            if (mConfigurations == null)
            {
                return false;
            }

            string value;
            return mConfigurations.TryGetValue(CurrentLanguage, LocalizationType.Video, key, out value);
        }
        
        public static string GetVideoValue(string key)
        {
            string value = string.Empty;
            if (mConfigurations != null)
            {
                mConfigurations.TryGetValue(CurrentLanguage, LocalizationType.Video, key, out value);
            }
            return value.FormatText();
        }
        
        public static async Task<VideoClip> GetVideoAssetAsync(string key, CancellationToken cancellationToken = default)
        {
            // 使用缓存
            if (mVideoCache.ContainsKey(key) && mVideoCache[key] != null)
            {
                return mVideoCache[key];
            }
            
            var videoValue = GetVideoValue(key);
            if (string.IsNullOrEmpty(videoValue))
            {
                Debug.LogWarning($"找不到键为 {key} 的视频资源");
                return null;
            }
            
            var assetPath = FileHelper.NormalizePathToForwardSlash(Path.Combine(mVideoAssetRootPath, _currentLanguage.ToString(), videoValue));
            var videoClip = await AssetHelper.LoadAssetAsync<VideoClip>(assetPath, cancellationToken);
            mVideoCache[key] = videoClip; // 添加到缓存
            return videoClip;
        }
        
        public static VideoClip GetVideoAssetSync(string key)
        {
            // 使用缓存
            if (mVideoCache.ContainsKey(key) && mVideoCache[key] != null)
            {
                return mVideoCache[key];
            }
            
            var videoValue = GetVideoValue(key);
            if (string.IsNullOrEmpty(videoValue))
            {
                Debug.LogWarning($"找不到键为 {key} 的视频资源");
                return null;
            }
            
            var assetPath = FileHelper.NormalizePathToForwardSlash(Path.Combine(mVideoAssetRootPath, _currentLanguage.ToString(), videoValue));
            var videoClip = AssetHelper.LoadAssetSync<VideoClip>(assetPath);
            mVideoCache[key] = videoClip; // 添加到缓存
            return videoClip;
        }

        #endregion


        #region Font

        private static string mFontAssetRootPath = string.Empty;
        
        public static void SetFontRootPath(string rootPath)
        {
            mFontAssetRootPath = rootPath;
        }
        
        public static bool ContainsFontKey(string key)
        {
            if (mConfigurations == null)
            {
                return false;
            }

            string value;
            return mConfigurations.TryGetValue(CurrentLanguage, LocalizationType.Font, key, out value);
        }
        
        public static string GetFontValue(string key)
        {
            string value = string.Empty;
            if (mConfigurations != null)
            {
                mConfigurations.TryGetValue(CurrentLanguage, LocalizationType.Font, key, out value);
            }
            return value.FormatText();
        }
        
        public static async Task<Font> GetFontAssetAsync(string key, CancellationToken cancellationToken = default)
        {
            // 使用缓存
            if (mFontCache.ContainsKey(key) && mFontCache[key] != null)
            {
                return mFontCache[key];
            }
            
            var fontValue = GetFontValue(key);
            if (string.IsNullOrEmpty(fontValue))
            {
                Debug.LogWarning($"找不到键为 {key} 的字体资源");
                return null;
            }
            
            var assetPath = FileHelper.NormalizePathToForwardSlash(Path.Combine(mFontAssetRootPath, _currentLanguage.ToString(), fontValue));
            var font = await AssetHelper.LoadAssetAsync<Font>(assetPath, cancellationToken);
            mFontCache[key] = font; // 添加到缓存
            return font;
        }
        
        public static Font GetFontAssetSync(string key)
        {
            // 使用缓存
            if (mFontCache.ContainsKey(key) && mFontCache[key] != null)
            {
                return mFontCache[key];
            }
            
            var fontValue = GetFontValue(key);
            if (string.IsNullOrEmpty(fontValue))
            {
                Debug.LogWarning($"找不到键为 {key} 的字体资源");
                return null;
            }
            
            var assetPath = FileHelper.NormalizePathToForwardSlash(Path.Combine(mFontAssetRootPath, _currentLanguage.ToString(), fontValue));
            var font = AssetHelper.LoadAssetSync<Font>(assetPath);
            mFontCache[key] = font; // 添加到缓存
            return font;
        }

        #endregion

        #region Prefab

        private static string mPrefabAssetRootPath = string.Empty;

        public static void SetPrefabRootPath(string rootPath)
        {
            mPrefabAssetRootPath = rootPath;
        }

        public static bool ContainsPrefabKey(string key)
        {
            if (mConfigurations == null)
            {
                return false;
            }
            
            string value;
            return mConfigurations.TryGetValue(CurrentLanguage, LocalizationType.Prefab, key, out value);
        }
        
        public static string GetPrefabValue(string key)
        {
            string value = string.Empty;
            if (mConfigurations != null)
            {
                mConfigurations.TryGetValue(CurrentLanguage, LocalizationType.Prefab, key, out value);
            }
            return value.FormatText();
        }
        
        public static async Task<GameObject> GetPrefabAssetAsync(string key, CancellationToken cancellationToken = default)
        {
            // 使用缓存
            if (mPrefabCache.ContainsKey(key) && mPrefabCache[key] != null)
            {
                return mPrefabCache[key];
            }
            
            var prefabValue = GetPrefabValue(key);
            if (string.IsNullOrEmpty(prefabValue))
            {
                Debug.LogWarning($"找不到键为 {key} 的预制体资源");
                return null;
            }
            
            var assetPath = FileHelper.NormalizePathToForwardSlash(Path.Combine(mPrefabAssetRootPath, _currentLanguage.ToString(), prefabValue));
            var prefab = await AssetHelper.LoadAssetAsync<GameObject>(assetPath, cancellationToken);
            mPrefabCache[key] = prefab; // 添加到缓存
            return prefab;
        }
        
        public static GameObject GetPrefabAssetSync(string key)
        {
            // 使用缓存
            if (mPrefabCache.ContainsKey(key) && mPrefabCache[key] != null)
            {
                return mPrefabCache[key];
            }
            
            var prefabValue = GetPrefabValue(key);
            if (string.IsNullOrEmpty(prefabValue))
            {
                Debug.LogWarning($"找不到键为 {key} 的预制体资源");
                return null;
            }
            
            var assetPath = FileHelper.NormalizePathToForwardSlash(Path.Combine(mPrefabAssetRootPath, _currentLanguage.ToString(), prefabValue));
            var prefab = AssetHelper.LoadAssetSync<GameObject>(assetPath);
            mPrefabCache[key] = prefab; // 添加到缓存
            return prefab;
        }
        
        #endregion

        #region ScriptableObject

        private static string mScriptableObjectAssetRootPath = string.Empty;

        public static void SetScriptableObjectRootPath(string rootPath)
        {
            mScriptableObjectAssetRootPath = rootPath;
        }

        public static bool ContainsScriptableObjectKey(string key)
        {
            if (mConfigurations == null)
            {
                return false;
            }
            
            string value;
            return mConfigurations.TryGetValue(CurrentLanguage, LocalizationType.ScriptableObject, key, out value);
        }
        
        public static string GetScriptableObjectValue(string key)
        {
            string value = string.Empty;
            if (mConfigurations != null)
            {
                mConfigurations.TryGetValue(CurrentLanguage, LocalizationType.ScriptableObject, key, out value);
            }
            return value.FormatText();
        }
        
        public static async Task<ScriptableObject> GetScriptableObjectAssetAsync(string key, CancellationToken cancellationToken = default)
        {
            // 使用缓存
            if (mScriptableObjectCache.ContainsKey(key) && mScriptableObjectCache[key] != null)
            {
                return mScriptableObjectCache[key];
            }
            
            var scriptableObjectValue = GetScriptableObjectValue(key);
            if (string.IsNullOrEmpty(scriptableObjectValue))
            {
                Debug.LogWarning($"找不到键为 {key} 的ScriptableObject资源");
                return null;
            }
            
            var assetPath = FileHelper.NormalizePathToForwardSlash(Path.Combine(mScriptableObjectAssetRootPath, _currentLanguage.ToString(), scriptableObjectValue));
            var scriptableObject = await AssetHelper.LoadAssetAsync<ScriptableObject>(assetPath, cancellationToken);
            mScriptableObjectCache[key] = scriptableObject; // 添加到缓存
            return scriptableObject;
        }
        
        public static async Task<T> GetScriptableObjectAssetAsync<T>(string key, CancellationToken cancellationToken = default) where T : ScriptableObject
        {
            var obj = await GetScriptableObjectAssetAsync(key, cancellationToken);
            return obj as T;
        }
        
        public static ScriptableObject GetScriptableObjectAssetSync(string key)
        {
            // 使用缓存
            if (mScriptableObjectCache.ContainsKey(key) && mScriptableObjectCache[key] != null)
            {
                return mScriptableObjectCache[key];
            }
            
            var scriptableObjectValue = GetScriptableObjectValue(key);
            if (string.IsNullOrEmpty(scriptableObjectValue))
            {
                Debug.LogWarning($"找不到键为 {key} 的ScriptableObject资源");
                return null;
            }
            
            var assetPath = FileHelper.NormalizePathToForwardSlash(Path.Combine(mScriptableObjectAssetRootPath, _currentLanguage.ToString(), scriptableObjectValue));
            var scriptableObject = AssetHelper.LoadAssetSync<ScriptableObject>(assetPath);
            mScriptableObjectCache[key] = scriptableObject; // 添加到缓存
            return scriptableObject;
        }
        
        public static T GetScriptableObjectAssetSync<T>(string key) where T : ScriptableObject
        {
            var scriptableObject = GetScriptableObjectAssetSync(key);
            return scriptableObject as T;
        }
        
        #endregion

        #region TextAsset

        private static string mTextAssetAssetRootPath = string.Empty;

        public static void SetTextAssetRootPath(string rootPath)
        {
            mTextAssetAssetRootPath = rootPath;
        }

        public static bool ContainsTextAssetKey(string key)
        {
            if (mConfigurations == null)
            {
                return false;
            }
            
            string value;
            return mConfigurations.TryGetValue(CurrentLanguage, LocalizationType.TextAsset, key, out value);
        }
        
        
        public static string GetTextAssetValue(string key)
        {
            string value = string.Empty;
            if (mConfigurations != null)
            {
                mConfigurations.TryGetValue(CurrentLanguage, LocalizationType.TextAsset, key, out value);
            }
            return value.FormatText();
        }
        
        public static async Task<TextAsset> GetTextAssetAsync(string key, CancellationToken cancellationToken = default)
        {
            // 使用缓存
            if (mTextAssetCache.ContainsKey(key) && mTextAssetCache[key] != null)
            {
                return mTextAssetCache[key];
            }
            
            var textAssetValue = GetTextAssetValue(key);
            if (string.IsNullOrEmpty(textAssetValue))
            {
                Debug.LogWarning($"找不到键为 {key} 的TextAsset资源");
                return null;
            }
            
            var assetPath = FileHelper.NormalizePathToForwardSlash(Path.Combine(mTextAssetAssetRootPath, _currentLanguage.ToString(), textAssetValue));
            var textAsset = await AssetHelper.LoadAssetAsync<TextAsset>(assetPath, cancellationToken);
            mTextAssetCache[key] = textAsset; // 添加到缓存
            return textAsset;
        }
        
        public static TextAsset GetTextAssetSync(string key)
        {
            // 使用缓存
            if (mTextAssetCache.ContainsKey(key) && mTextAssetCache[key] != null)
            {
                return mTextAssetCache[key];
            }
            
            var textAssetValue = GetTextAssetValue(key);
            if (string.IsNullOrEmpty(textAssetValue))
            {
                Debug.LogWarning($"找不到键为 {key} 的TextAsset资源");
                return null;
            }
            
            var assetPath = FileHelper.NormalizePathToForwardSlash(Path.Combine(mTextAssetAssetRootPath, _currentLanguage.ToString(), textAssetValue));
            var textAsset = AssetHelper.LoadAssetSync<TextAsset>(assetPath);
            mTextAssetCache[key] = textAsset; // 添加到缓存
            return textAsset;
        }
        
        #endregion
        
    }
}